using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Extensions;

namespace ReaWTM.LayuiHelper
{
	[HtmlTargetElement("wt:combobox", Attributes = REQUIRED_ATTR_NAME, TagStructure = TagStructure.WithoutEndTag)]
	public class ComboBoxTagHelper : BaseFieldTag
	{
		public string TextKey { get; set; } = "Text";
		public string ValueKey { get; set; } = "Value";
		public int Delay { get; set; } = 600;

		public bool AutoComplete { get; set; }

		public string YesText { get; set; }

		public string NoText { get; set; }

		/// <summary>
		/// 启用搜索
		/// 注意：多选与搜索不能同时启用
		/// </summary>
		public bool EnableSearch { get; set; }

		public ModelExpression Items { get; set; }

		public ModelExpression LinkField { get; set; }

		public string LinkId { get; set; }
		public string TriggerUrl { get; set; }

		/// <summary>
		/// 是否多选
		/// 默认根据Field 绑定的值类型进行判断。Array or List 即多选，否则单选
		/// 注意：多选与搜索不能同时启用
		/// </summary>
		public bool? MultiSelect { get; set; }

		/// <summary>
		/// 改变选择时触发的js函数，func(data)格式;
		/// data.elem得到select原始DOM对象;
		/// data.value得到被选中的值;
		/// data.othis得到美化后的DOM对象;
		/// triggerUrl为闭包参数，可直接在ChangeFunc访问到
		/// 返回false则会阻止triggerUrl的请求
		/// </summary>
		public string ChangeFunc { get; set; }

		private WTMContext _wtm;

		public ComboBoxTagHelper(IOptionsMonitor<Configs> configs, WTMContext wtm)
		{
			if (EmptyText == null)
			{
				EmptyText = THProgram._localizer["Sys.PleaseSelect"];
			}
			EnableSearch = configs.CurrentValue.UIOptions.ComboBox.DefaultEnableSearch;
			_wtm = wtm;
		}

		private Type _modeltype;

		private void SetMultiSelect(TagHelperOutput output)
		{
			_modeltype = Field.Metadata.ModelType;
			if (MultiSelect == null)
			{
				MultiSelect = false;
				if (Field.Name.Contains("[") || _modeltype.IsArray || _modeltype.IsList())// Array or List
				{
					MultiSelect = true;
				}
			}
		}

		private void SetLink(TagHelperOutput output)
		{
			if (LinkField != null)
			{
				output.Attributes.Add("wtm-linkto", LinkField.Name);
			}
		}


		private List<ComboSelectListItem> GetItems()
		{
			var listItems = new List<ComboSelectListItem>();

			if (ItemUrl != null)
			{
				return listItems;
			}

			if (Items?.Model == null) // 添加默认下拉数据源
			{
				var checktype = _modeltype;
				if (_modeltype.IsGenericType && typeof(List<>).IsAssignableFrom(_modeltype.GetGenericTypeDefinition()))
				{
					checktype = _modeltype.GetGenericArguments()[0];
				}

				if (checktype.IsEnumOrNullableEnum())
				{
					listItems = checktype.ToListItems(DefaultValue ?? Field.Model);
				}
				else if (checktype == typeof(bool) || checktype == typeof(bool?))
				{
					bool? df = null;
					if (bool.TryParse(DefaultValue ?? "", out bool test) == true)
					{
						df = test;
					}
					listItems = Utils.GetBoolCombo(BoolComboTypes.Custom, df ?? (bool?)Field.Model, YesText, NoText);
				}
			}
			else // 添加用户设置的设置源
			{
				if (typeof(IEnumerable<ComboSelectListItem>).IsAssignableFrom(Items.Metadata.ModelType))
				{
					if (typeof(IEnumerable<TreeSelectListItem>).IsAssignableFrom(Items.Metadata.ModelType))
					{
						listItems = (Items.Model as IEnumerable<TreeSelectListItem>).FlatTreeSelectList().Cast<ComboSelectListItem>().ToList();
					}
					else
					{
						listItems = (Items.Model as IEnumerable<ComboSelectListItem>).ToList();
					}
				}
			}
			return listItems;
		}

		protected override string GetDefaultValue()
		{
			object defaultValue = DefaultValue;
			if (Field.Model != null)
			{
				defaultValue = Field.Model;
			}

			if (defaultValue == null)
			{
				return "[]";
			}

			var temp = JsonSerializer.Serialize(defaultValue, JsonOptions2);
			if (MultiSelect.Value) return temp;
			else return $"[{temp}]";
		}
		protected override void SetName(TagHelperContext context, TagHelperOutput output)
		{ }
		public override void Process(TagHelperContext context, TagHelperOutput output)
		{
			SetDefaultEmpty(THProgram._localizer["Sys.PleaseSelect"]);

			StringBuilder builder = new StringBuilder();
			_modeltype = Field.Metadata.ModelType;
			output.TagName = "input";
			output.TagMode = TagMode.StartTagAndEndTag;
			output.Attributes.Add("wtm-ctype", "combobox");
			output.Attributes.Add("type", "hidden");
			SetMultiSelect(output);
			SetLink(output);

			builder.Append($@"<div id='div{Id}'/>");
			builder.Append($@"
<script>
wtm.combobox_Render({{
id:'{Id}',
changeFunc:'{ChangeFunc}',
data:{JsonSerializer.Serialize(GetItems(), JsonOptions)},
delay:100,
disabled:{GetBooleanString(Disabled)},
fieldName:'{GetName(context)}',
initValue:{GetDefaultValue()},
multi:{GetBooleanString(MultiSelect)},
textKey:'{TextKey}',
emptyText:'{EmptyText}',
url:'{ItemUrl}',
valueKey:'{ValueKey}',
beforeMount:'{BeforeMount}',
mounted:'{Mounted}',
triggerUrl:'{TriggerUrl}',
}});
</script>
");

			output.PostElement.AppendHtml(builder.ToString());
			base.Process(context, output);
		}
	}
}